// -----------------------------------------------------------------------
//  <copyright file="ResourceController.cs" company="LiuliuSoft">
//      Copyright (c) 2022-2025 DaprPlus. All rights reserved.
//  </copyright>
//  <site>https://dapr.plus</site>
//  <last-editor>郭明锋</last-editor>
//  <last-date>2025-03-12 19:03</last-date>
// -----------------------------------------------------------------------

using DaprPlus.MediatR;
using Microsoft.Extensions.Options;
using OSharp.Filter;


namespace Liuliu.Fsb.ApiGateway.Controllers;

[ApiResultWrapperFilter]
public class ResourceController(IServiceProvider provider) : ApiControllerBase
{
    [HttpGet("node/{roleId}")]
    [Produces<Dictionary<string, List<ResourceNode>>>]
    public async Task<IActionResult> GetEntityResourceNode(long roleId)
    {
        var options = ServiceProvider.GetRequiredService<IOptions<DaprOptions>>().Value;
        var appIds = options.AppIds.Values.ToArray();
        if (appIds.Length == 0)
        {
            return BadRequest(new ApiResult
            {
                ResultType = ApiResultType.Error,
                Message = "服务列表不能为空"
            });
        }

        var requests = appIds.ToDictionary(
            service => service,
            service => provider.CreateInvokeMethodRequest(HttpMethod.Get, service, $"/api/resource/node/{roleId}"));

        var daprClient = provider.GetRequiredService<DaprClient>();
        var tasks = requests.ToDictionary(
            kvp => kvp.Key,
            kvp => daprClient.InvokeMethodAsync<ApiResult<List<ResourceNode>>>(kvp.Value));

        await Task.WhenAll(tasks.Values);

        var resultDict = tasks.ToDictionary(
            kvp => kvp.Key,
            kvp => kvp.Value.Result.IsSuccess() && kvp.Value.Result.Data?.Count > 0
                ? kvp.Value.Result.Data!
                : new List<ResourceNode>());

        return Ok(resultDict);
    }

    [HttpPost("read")]
    [Produces<PageResult<ResourceOutDto>>]
    public async Task<IActionResult> Read([FromBody] ResourcePageQuery query)
    {
        var request = provider.CreateInvokeMethodRequest(query.Service, "/api/resource/read", query.Query);
        var daprClient = provider.GetRequiredService<DaprClient>();
        var result = await daprClient.InvokeMethodAsync<ApiResult<PageResult<ResourceOutDto>>>(request);
        return Ok(result);
    }

    [HttpPost]
    [Produces<ApiResult>]
    public async Task<IActionResult> Create([FromBody] ResourceInModel model)
    {
        var request = provider.CreateInvokeMethodRequest(HttpMethod.Post, model.Service, "/api/resource", model);
        var daprClient = provider.GetRequiredService<DaprClient>();
        var result = await daprClient.InvokeMethodAsync<ApiResult>(request);
        return Ok(result);
    }

    [HttpPut()]
    [Produces<ApiResult>]
    public async Task<IActionResult> Update([FromBody] ResourceInModel model)
    {
        var request = provider.CreateInvokeMethodRequest(HttpMethod.Put, model.Service, "/api/resource", model);
        var daprClient = provider.GetRequiredService<DaprClient>();
        var result = await daprClient.InvokeMethodAsync<ApiResult>(request);
        return Ok(result);
    }

    [HttpDelete()]
    [Produces<ApiResult>]
    public async Task<IActionResult> Delete([FromBody] ResourceDeleteModel model)
    {
        var request = provider.CreateInvokeMethodRequest(HttpMethod.Delete, model.Service, "/api/resource", model.Ids);
        var daprClient = provider.GetRequiredService<DaprClient>();
        var result = await daprClient.InvokeMethodAsync<ApiResult>(request);
        return Ok(result);
    }
}

#region 相关类型

public class ResourcePageQuery
{
    public required string Service { get; set; }
    public required PageQuery<PageResult<ResourceOutDto>> Query { get; set; }
}

public class ResourceInModel
{
    public required string Service { get; set; }
    public required ResourceInDto[] Dtos { get; set; }
}

public class ResourceDeleteModel
{
    public required string Service { get; set; }
    public required long[] Ids { get; set; }
}

public class ResourceNode
{
    public long Id { get; set; }
    public required string Name { get; set; }
    public required string Code { get; set; }
    public string? Description { get; set; }
    public ResourceType Type { get; set; }
    public bool IsSelected { get; set; }
    public string[] Operations { get; set; } = [];
    public ResourceOperation[] AllowedOperations { get; set; } = [];
}

public class ResourceOutDto
{
    public long Id { get; set; }
    public required string Name { get; set; }
    public required string Code { get; set; }
    public string? Description { get; set; }
    public required string ServiceName { get; set; }
    public ResourceType Type { get; set; }
    public ResourceAccessType AccessType { get; set; }
    public bool IsSystem { get; set; }
    public bool IsLocked { get; set; }
    public Dictionary<string, object> Metadata { get; set; } = [];
    public ResourceOperation[] AllowedOperations { get; set; } = [];
}

public class ResourceInDto
{
    public long Id { get; set; }
    public required string Name { get; set; }
    public required string Code { get; set; }
    public string? Description { get; set; }
    public required string ServiceName { get; set; }
    public ResourceType Type { get; set; }
    public ResourceAccessType AccessType { get; set; }
    public bool IsLocked { get; set; }
    public Dictionary<string, object>? Metadata { get; set; }
    public ResourceOperation[]? AllowedOperations { get; set; }
}

#endregion
